﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Diagnostics;

namespace Security.Authorizations
{
    internal static class WCFExtension
    {
        /// <summary>
        /// Safely closes a service client connection.
        /// </summary>
        /// <param name="myServiceClient">The client connection to close.</param>
        public static void CloseConnection(this ICommunicationObject service)
        {
            if (service.State != CommunicationState.Opened)
            {
                return;
            }

            try
            {
                service.Close();
            }
            catch (CommunicationException ex)
            {
                Debug.Print(ex.ToString());
                var error =
                    new WebAuthorizationErrorEvent(ex.Message, service, AuthorizationEventCode.ServiceError, ex);
                service.Abort();
                error.Raise();
            }
            catch (TimeoutException ex)
            {
                Debug.Print(ex.ToString());
                var error =
                    new WebAuthorizationErrorEvent(ex.Message, service, AuthorizationEventCode.ServiceError, ex);
                service.Abort();
                error.Raise();
            }
            catch (Exception ex)
            {
                Debug.Print(ex.ToString());
                var error =
                    new WebAuthorizationErrorEvent(ex.Message, service, AuthorizationEventCode.ServiceError, ex);

                service.Abort();
                error.Raise();
                throw;
            }
        }

        //Cria uma expressa Lambda para executar os metodos dos serviço de forma que feche automaticamente e log os erros automaticamente
        public static TResult SafeExecution<TExtension, TResult>(this TExtension service, Func<TExtension, TResult> serviceAction) where TExtension : ICommunicationObject
        {

            TResult outValue;

            try
            {
                outValue = serviceAction.Invoke(service);
            }
            catch (Exception ex)
            {
                Debug.Print(ex.ToString());
                var error =
                    new WebAuthorizationErrorEvent(ex.Message, service, AuthorizationEventCode.ServiceError, ex);

                error.Raise();
                throw;
            }
            finally
            {
                service.CloseConnection();
            }

            return outValue;
        }


        public static void SafeExecution<TExtension>(this TExtension service, Action<TExtension> serviceAction) where TExtension : ICommunicationObject
        {

            try
            {
                serviceAction.Invoke(service);
            }
            catch (Exception ex)
            {
                Debug.Print(ex.ToString());
                var error =
                    new WebAuthorizationErrorEvent(ex.Message, service, AuthorizationEventCode.ServiceError, ex);

                error.Raise();
                throw;
            }
            finally
            {
                service.CloseConnection();
            }
        }
    }
}
